#ifndef LIB_BITOP_H
    #define LIB_BITOP_H

    #include <lib/type.h>

    #define low8(val) ((val)&0xff)
    #define high8(val) (((val) >> 8) & 0xff)

    #define low16(val) ((val)&0xffff)
    #define high16(val) (((val) >> 16) & 0xffff)

    #define low32(val) ((val)&0xffffffff)
    #define high32(val) (((val) >> 32) & 0xffffffff)

    #define merge8(a, b) (uint8_t)(((a)&0xf) << 4 | ((b)&0xf))
    #define merge16(a, b) (uint16_t)(((a)&0xff) << 8 | (b)&0xff)
    #define merge32(a, b) (uint32_t)(((a)&0xffff) << 16 | (b)&0xffff)

    static uint64_t set_bit(int x, uint64_t *bits)
    {
        (x < 32) ? (*bits |= (1 << x)) : (*(bits + (x >> 5)) |= (1 << (x & 0x1f)));
        return  *bits;
    }

    static uint64_t clear_bit(int x, uint64_t *bits)
    {
        (x < 32) ? (*bits &= ~(1 << x)) : (*(bits + (x >> 5)) &= ~(1 << (x & 0x1f)));
        return *bits;
    }

    static uint64_t test_bit(int x, uint64_t *bits)
    {
        return (x < 32) ? (*bits & (1 << x)) : (*(bits + (x >> 5)) & (1 << (x & 0x1f)));;
    }

#endif